﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using PocketBook.Domain.Abstract;
using System.Linq.Expressions;
using PocketBook.Domain.Entities;
using System.Xml.Linq;
using System.IO;

namespace PocketBook.Domain.Concrete
{
    public class Repository : IRepository
    {
        private XDocument _expenseContext;
        private XDocument _incomesContext;
        private string _expensePath;
        private string _incomesPath;

        public Repository()
        {
            string documents = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
            _expensePath = Path.Combine(documents + "\\Pocket Book Data\\expenses.xml");
            _expenseContext = XDocument.Load(_expensePath);
            
            _incomesPath = Path.Combine(documents + "\\Pocket Book Data\\incomes.xml");
            _incomesContext = XDocument.Load(_incomesPath);
        }

        #region Expenses

        public List<Expense> GetExpenses()
        {
            _expenseContext = XDocument.Load(_expensePath);
            var expenses = _expenseContext.Element("expenses").Elements("expense");
            if (expenses != null)
            {
                return expenses
                    .Select(n =>
                        new Expense
                        {
                            ExpenseId = Guid.Parse(n.Element("id").Value),
                            Name = n.Element("name").Value,
                            Date = DateTime.Parse(n.Element("date").Value),
                            Amount = decimal.Parse(n.Element("amount").Value),
                            Description = n.Element("description").Value
                        }).ToList();
            }
            else
            {
                return new List<Expense>();
            }
        }

        public List<Expense> GetExpenses(Func<Expense, bool> where)
        {
            return this.GetExpenses().Where(where).ToList();
        }

        public Expense AddExpense(Expense expense)
        {
            _expenseContext.Element("expenses")
                .Add(new XElement("expense",
                    new XElement("id", expense.ExpenseId.ToString()),
                    new XElement("name", expense.Name),
                    new XElement("date", DateTime.Now.ToString()),
                    new XElement("amount", expense.Amount.ToString()),
                    new XElement("description", expense.Description)));
            _expenseContext.Save(_expensePath);
            return expense;
        }

        public void UpdateExpense(Expense expense)
        {
            var id = expense.ExpenseId;
            _expenseContext.Element("expenses")
                .Elements("expense")
                .SingleOrDefault(n => n.Element("id").Value == id.ToString())
                .Remove();
            _expenseContext.Element("expenses")
                .Add(new XElement("expense",
                    new XElement("id", id.ToString()),
                    new XElement("name", expense.Name),
                    new XElement("date", DateTime.Now.ToString()),
                    new XElement("amount", expense.Amount.ToString()),
                    new XElement("description", expense.Description)));
            _expenseContext.Save(_expensePath);
        }

        public void DeleteExpanse(Guid id)
        {
            _expenseContext.Element("expenses")
                .Elements("expense")
                .SingleOrDefault(n => n.Element("id").Value == id.ToString())
                .Remove();
            _expenseContext.Save(_expensePath);
        }

        #endregion

        #region Incomes

        public List<Income> GetIncomes()
        {
            _incomesContext = XDocument.Load(_incomesPath);
            var incomes = _incomesContext.Element("incomes").Elements("income");
            if (incomes != null)
            {
                return incomes
                    .Select(n =>
                        new Income
                        {
                            IncomeId = Guid.Parse(n.Element("id").Value),
                            Name = n.Element("name").Value,
                            Date = DateTime.Parse(n.Element("date").Value),
                            Amount = decimal.Parse(n.Element("amount").Value),
                            Description = n.Element("description").Value
                        }).ToList();
            }
            else
            {
                return new List<Income>();
            }

        }

        public List<Income> GetIncomes(Func<Income, bool> where)
        {
            return this.GetIncomes().Where(where).ToList();
        }

        public Income AddIncome(Income income)
        {
            _incomesContext.Element("incomes")
                .Add(new XElement("income",
                    new XElement("id", income.IncomeId.ToString()),
                    new XElement("name", income.Name),
                    new XElement("date", DateTime.Now.ToString()),
                    new XElement("amount", income.Amount.ToString()),
                    new XElement("description", income.Description)));
            _incomesContext.Save(_incomesPath);
            return income;
        }

        public void UpdateIncome(Income income)
        {
            var id = income.IncomeId;
            _incomesContext.Element("incomes")
                .Elements("income")
                .SingleOrDefault(n => n.Element("id").Value == id.ToString())
                .Remove();
            _incomesContext.Element("incomes")
                .Add(new XElement("income",
                    new XElement("id", id.ToString()),
                    new XElement("name", income.Name),
                    new XElement("date", DateTime.Now.ToString()),
                    new XElement("amount", income.Amount.ToString()),
                    new XElement("description", income.Description)));
            _incomesContext.Save(_incomesPath);
        }

        public void DeleteIncome(Guid id)
        {
            _incomesContext.Element("incomes")
                .Elements("income")
                .SingleOrDefault(n => n.Element("id").Value == id.ToString())
                .Remove();
            _incomesContext.Save(_incomesPath);
        }

        #endregion
    }
}
